package com.trinity.uniquefees.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.trinity.campus.domain.CampusStudents;
import com.trinity.campus.service.ICampusStudentsService;
import com.trinity.common.core.domain.entity.SysDept;
import com.trinity.common.exception.ServiceException;
import com.trinity.common.utils.StringUtils;
import com.trinity.common.utils.bean.BeanUtils;
import com.trinity.common.utils.bean.BeanValidators;
import com.trinity.payment.domain.ListStudentBookDao;
import com.trinity.system.service.ISysDeptService;
import com.trinity.uniquefees.domain.UfBookList;
import com.trinity.uniquefees.domain.bo.UfCourseBook;
import com.trinity.uniquefees.domain.bo.UfStudentBook;
import com.trinity.uniquefees.domain.vo.UfStudentBookVO;
import com.trinity.uniquefees.dto.CourseDto;
import com.trinity.uniquefees.dto.DeptSemesterStuCourseDto;
import com.trinity.uniquefees.dto.UfStudentBookDto;
import com.trinity.uniquefees.mapper.UfPayListStuMapper;
import com.trinity.uniquefees.mapper.UfStudentBookMapper;
import com.trinity.uniquefees.service.IUfBookListService;
import com.trinity.uniquefees.service.IUfCourseBookService;
import com.trinity.uniquefees.service.IUfStudentBookService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订购教程名单Service业务层处理
 *
 * @author 董诗攀
 * @date 2023-12-11
 */
@Service
public class UfStudentBookServiceImpl extends ServiceImpl<UfStudentBookMapper, UfStudentBook> implements IUfStudentBookService {
    @Resource
    private UfStudentBookMapper ufStudentBookMapper;
    @Resource
    private IUfCourseBookService ufCourseBookService;

    @Resource
    private IUfBookListService ufBookListService;
    @Resource
    private ICampusStudentsService studentsService;
    @Resource
    private UfPayListStuMapper ufPayListStuMapper;

    @Resource
    private ISysDeptService sysDeptService;

    @Resource
    protected Validator validator;

    /**
     * 查询订购教程名单
     *
     * @param csId 订购教程名单主键
     * @return 订购教程名单
     */
    @Override
    public UfStudentBook selectUfStudentBookByCsId(String csId) {
        // 构建查询条件
        Wrapper<UfStudentBook> queryWrapper = new QueryWrapper<UfStudentBook>()
                .eq("course_id", csId);
        return ufStudentBookMapper.selectOne(queryWrapper);
    }

    /**
     * 查询订购教程名单列表
     *
     * @param ufStudentBook 订购教程名单
     * @return 订购教程名单
     */
    @Override
    public List<UfStudentBook> selectUfStudentBookList(UfStudentBook ufStudentBook) {
//        return ufStudentBookMapper.selectUfStudentBookList(ufStudentBook);
        // 构建查询条件
        QueryWrapper<UfStudentBook> queryWrapper = new QueryWrapper<>(ufStudentBook);
        return ufStudentBookMapper.selectList(queryWrapper);
    }

    @Override
    public List<ListStudentBookDao> selectPaymentListDto(UfStudentBook ufStudentBook) {
        return ufStudentBookMapper.selectStudentBookWithDetails();
    }

    /**
     * 根据班级查询
     * 查询订购教程名单列表
     *
     * @param courseIds 课程的Id
     * @return 订购教程名单
     */
    public List<UfStudentBook> selectUfStudentBookList(List<Long> courseIds) {
        if (courseIds == null || courseIds.isEmpty()) {
            // courseIds 为空，根据需求返回空列表或者抛出异常
            return Collections.emptyList();
        }
        // 创建 QueryWrapper 对象
        QueryWrapper<UfStudentBook> queryWrapper = new QueryWrapper<>();
        // 使用 in 条件
        queryWrapper.in("course_id", courseIds);
        return ufStudentBookMapper.selectList(queryWrapper);
    }

    /**
     * 根据缴费项目
     * 查询订购教程名单列表
     *
     * @param listId 缴费项目
     * @return 订购教程名单
     */
    public List<UfStudentBook> selectStuBookListByListId(String listId) {
        // 创建 QueryWrapper 对象
        QueryWrapper<UfStudentBook> queryWrapper = new QueryWrapper<>();
        // 使用 in 条件
        queryWrapper.in("list_id", listId);
        return ufStudentBookMapper.selectList(queryWrapper);
    }

    @Override
    public DeptSemesterStuCourseDto selectUfDeptSemesterStuCourse(UfCourseBook courseBook) {
        return selectListStuCourse(courseBook.getScheduleId());
    }

    /**
     * 根据 listId 查询缴费名单
     *
     * @param scheduleId listId
     * @return re
     */
    @Override
    public DeptSemesterStuCourseDto selectListStuCourse(String scheduleId) {
        DeptSemesterStuCourseDto resultVo = new DeptSemesterStuCourseDto();
        if (StringUtils.isBlank(scheduleId)) {
            throw new ServiceException("参数异常：scheduleId");
        }
        UfBookList ufBookList = ufBookListService.selectUfBookListById(scheduleId);
        if (ufBookList == null) {
            throw new ServiceException("数据异常：ufBookList");
        }
        resultVo.setTitle(ufBookList.getName());

        Long deptId = ufBookList.getDeptId();
        resultVo.setDeptId(String.valueOf(deptId));
        //班级学生
        List<CampusStudents> students = studentsService.selectCampusStudentsListByDeptId(deptId);
        List<UfStudentBookDto> ufStudentBookDtos = buildStudent(students);
        resultVo.setCourseStu(ufStudentBookDtos);

        //书籍列表 根据数目清单id 查询 个性化缴费需要添加 书籍订购名单
        if (ufBookList.getOther() != null && ufBookList.getOther().equals("UNIQUE")) {
            List<UfCourseBook> ufCourseBooks = ufCourseBookService.selectUfCourseBookByListId(scheduleId);
            buildStudentBook(resultVo, ufCourseBooks);
        }
        return resultVo;
    }

    private List<UfStudentBookDto> buildStudent(List<CampusStudents> students) {
        List<UfStudentBookDto> stuBook = new ArrayList<>();
        for (CampusStudents student : students) {
            UfStudentBookDto stuBookDto = new UfStudentBookDto();
            //拷贝学生信息
            BeanUtils.copyBeanProp(stuBookDto, student);
            stuBook.add(stuBookDto);
        }
        return stuBook;
    }

    private void buildStudentBook(DeptSemesterStuCourseDto resultVo, List<UfCourseBook> ufCourseBooks) {
        List<UfStudentBookDto> courseStu = resultVo.getCourseStu();
        Map<Long, List<Long>> stuCourses;
        if (ufCourseBooks == null || ufCourseBooks.isEmpty()) {
            return;
        }
        resultVo.setCourseBooks(ufCourseBooks);

        //获取课程的id
        List<Long> courseIds = ufCourseBooks.stream().map(UfCourseBook::getCourseId).collect(Collectors.toList());
        //查询该班级 该学期的 订书名单
        List<UfStudentBook> list = selectUfStudentBookList(courseIds);
        stuCourses = list.stream()
                .collect(Collectors.groupingBy(UfStudentBook::getStuId,
                        Collectors.mapping(UfStudentBook::getCourseId, Collectors.toList())));
        List<UfStudentBookDto> stuBook = new ArrayList<>();
        Long totalPrice = 0L;
        for (UfStudentBookDto stuBookDto : courseStu) {
            Long stuTotalPrice = 0L;
            //构建一个学生订阅书籍的列表
            Set<CourseDto> courseDtoList = new LinkedHashSet<>();
            //检查学生订阅的书籍
            for (UfCourseBook course : ufCourseBooks) {
                CourseDto courseDto = new CourseDto();
                //拷贝课程信息
                BeanUtils.copyBeanProp(courseDto, course);
                courseDto.setCourseId(String.valueOf(course.getCourseId()));
                courseDto.setPrice(String.valueOf(course.getPrice()));
                //未订阅
                courseDto.setSubscribe(false);
                if (stuCourses.containsKey(stuBookDto.getStudentId())) {
                    List<Long> stuCourseIds = stuCourses.get(stuBookDto.getStudentId());
                    //订阅了该课程
                    if (stuCourseIds.contains(course.getCourseId())) {
                        courseDto.setSubscribe(true);
                        stuTotalPrice += course.getPrice();
                    }
                }
                stuBookDto.setTotalPrice(String.valueOf(stuTotalPrice));
                courseDtoList.add(courseDto);

            }
            stuBookDto.setCourses(courseDtoList);
            stuBook.add(stuBookDto);
            totalPrice += stuTotalPrice;
        }
        resultVo.setCourseStu(stuBook);

        resultVo.setTotalPrice(String.valueOf(totalPrice));
    }

    /**
     * 将单位为分的价格格式化为保留两位小数的格式
     * 2299  ->  22.99￥
     */
    public String formatPrice(Long price) {
        if (price == 0) {
            return "";
        }
        double amountInDollars = (double) price / 100.00;
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        return decimalFormat.format(amountInDollars);
    }

    private String getDeptName(SysDept dept) {
        String ancestors = dept.getAncestors();
        Long[] array = Arrays.stream(ancestors.split(","))
                .map(Long::parseLong)
                .toArray(Long[]::new);
        List<SysDept> depts = sysDeptService.selectDeptAncestors(array);
        //排除目录
        List<SysDept> filteredDepts = depts.stream()
                .filter(sysDept -> !"M".equals(sysDept.getDeptType()))
                .collect(Collectors.toList());

        // 将过滤后的 List 转为 Map，以 deptId 作为键
        Map<Long, SysDept> result = filteredDepts.stream()
                .collect(Collectors.toMap(SysDept::getDeptId, sysDept -> sysDept));
        //拼接名称
        String name = "";
        for (Long id : array) {
            SysDept item = result.get(id);
            if (item != null) {
                if (StringUtils.isBlank(name)) {
                    name = item.getDeptName();
                } else {
                    name = name + "-" + item.getDeptName();
                }
            }
        }

        return name + "-" + dept.getDeptName();
    }

    /**
     * 新增订购教程名单
     *
     * @param ufStudentBook 订购教程名单
     * @return 结果
     */
    @Override
    public int insertUfStudentBook(UfStudentBook ufStudentBook) {
        return ufStudentBookMapper.insert(ufStudentBook);
    }

    /**
     * 修改订购教程名单
     *
     * @param ufStudentBook 订购教程名单
     * @return 结果
     */
    @Override
    public int updateUfStudentBook(UfStudentBook ufStudentBook) {
        QueryWrapper<UfStudentBook> queryWrapper = new QueryWrapper<>(ufStudentBook);
        return ufStudentBookMapper.update(ufStudentBook, queryWrapper);
    }

    /**
     * 批量删除订购教程名单
     *
     * @param csIds 需要删除的订购教程名单主键
     * @return 结果
     */
    @Override
    public int deleteUfStudentBookByCsIds(String[] csIds) {
        List<String> idList = Arrays.stream(csIds).collect(Collectors.toList());
        return ufStudentBookMapper.deleteBatchIds(idList);
    }

    /**
     * 删除订购教程名单信息
     *
     * @param csId 订购教程名单主键
     * @return 结果
     */
    @Override
    public int deleteUfStudentBookByCsId(String csId) {
        String[] split = csId.split("-");
        Wrapper<UfStudentBook> queryWrapper = new QueryWrapper<UfStudentBook>()
                .eq("stu_id", split[0])
                .eq("course_id", split[1]);
        return ufStudentBookMapper.delete(queryWrapper);
    }

    /**
     * 根据缴费项目删除订单
     *
     * @param listId
     * @return
     */
    public int deleteUfStudentBookByListId(String listId) {
        LambdaQueryWrapper<UfStudentBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UfStudentBook::getScheduleId, listId); // 根据缴费项目进行删除
        return ufStudentBookMapper.delete(queryWrapper);
    }

    @Override
    public String importBill(List<UfStudentBookVO> list, String listId, String operName,
                             List<CampusStudents> students, List<UfCourseBook> course) {
        if (list == null || list.isEmpty()) {
            throw new ServiceException("导入教材数据不能为空！");
        }

        final String STUDENT_NOT_EXIST = ":学生信息不存在";
        final String COURSE_NOT_EXIST = ":课程信息不存在";

        int successNum = 0;
        int failureNum = 0;

        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        // 先删除原先账单
        deleteUfStudentBookByListId(listId);

        //去重
        // 根据组合属性进行去重 (学生 -- 课程)  一个课程学生只能选一次
        List<UfStudentBookVO> distinctBills = list.stream().distinct().collect(Collectors.toList());

        //课程 --> 教材
        Map<String, List<UfCourseBook>> groupedByCourseName = course.stream()
                .collect(Collectors.groupingBy(UfCourseBook::getCourseName));

        //获取学士列表
        Map<String, CampusStudents> stuMap = students.stream()
                .collect(Collectors.toMap(CampusStudents::getStudentName, Function.identity(), (existing, replacement) -> replacement));

        for (UfStudentBookVO bill : distinctBills) {
            BeanValidators.validateWithException(validator, bill);
            String studentName = bill.getStudentName();
            String courseName = bill.getCourseName();
            String msg = String.format("<br/>%d、: %s【%s】", failureNum + 1, studentName, courseName);

            try {
                if (!stuMap.containsKey(studentName)) {
                    failureNum++;
                    failureMsg.append(msg).append(STUDENT_NOT_EXIST);
                    continue;
                }

                if (!groupedByCourseName.containsKey(courseName)) {
                    failureNum++;
                    failureMsg.append(msg).append(COURSE_NOT_EXIST);
                    continue;
                }
                Long stuId = stuMap.get(studentName).getStudentId();
                List<UfCourseBook> ufCourseBooks = groupedByCourseName.get(courseName);
                for (UfCourseBook book : ufCourseBooks) {
                    UfStudentBook ufStudentBook = new UfStudentBook();
                    //设置缴费项目
                    ufStudentBook.setScheduleId(listId);
                    //设置学生
                    ufStudentBook.setStuId(stuId);
                    //设置课程
                    ufStudentBook.setCourseId(book.getCourseId());
                    ufStudentBookMapper.insert(ufStudentBook);
                    successNum++;
                    successMsg.append(String.format(
                            "<br/>%d、%s: 【%s】 《%s》", successNum, studentName, courseName, book.getCourseBook()));
                }

            } catch (Exception e) {
                failureNum++;
                failureMsg.append(msg).append(":").append(e.getMessage());
                log.error(msg, e);
            }
        }

        return buildResultMessage(successNum, failureNum, successMsg, failureMsg);

    }

    /**
     * 返回值
     *
     * @param successNum
     * @param failureNum
     * @param successMsg
     * @param failureMsg
     * @return
     */
    private String buildResultMessage(int successNum, int failureNum, StringBuilder successMsg, StringBuilder failureMsg) {

        if (failureNum > 0) {
            successMsg.insert(0, "导入成功数据，共 " + successNum + " 条，数据如下：");
            failureMsg.insert(0, "导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(successMsg.append("<br/><br/>").append(failureMsg).toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
}
